home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample SMSAM / SampleSMSAM Source / TupleDatabase / ADASTupleDatabase.cp next >
Encoding:
Text File  |  1995-07-28  |  24.0 KB  |  832 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ADASTupleDatabase.cp
  3.  
  4.     Copyright:    © 1991-1994 by Apple Computer, Inc.
  5.                 All rights reserved.
  6.  
  7.     Part of the AOCE Sample SMSAM Package.  Consult the license
  8.     which came with this software for your specific legal rights.
  9.  
  10. */
  11.  
  12.  
  13. #if 0
  14. #ifndef __BLJSTANDARDINCLUDES__
  15. #include "BLJStandardIncludes.h"
  16. #endif
  17.  
  18. #ifndef __ADASTUPLEDATABASE__
  19. #include "ADASTupleDatabase.h"
  20. #endif
  21.  
  22. #ifndef __OCEERRORS__
  23. #include "OCEErrors.h"
  24. #endif
  25.  
  26. #ifndef __UTILITIES__
  27. #include "Utilities.h"
  28. #endif
  29.  
  30. #ifndef __DEBUGGINGGEAR__
  31. #include "DebuggingGear.h"
  32. #endif
  33.  
  34. #ifndef __AYSTHREADGLUE__
  35. #include "AYSThreadGlue.h"
  36. #endif
  37.  
  38. #ifndef __BLJOCEUTILITIES__
  39. #include "BLJOCEUtilities.h"
  40. #endif
  41.  
  42. inline short shortmin(short a, short b) { return (a < b) ? a : b; };
  43.  
  44. //    This macro 'references' a variable, so that a '# warning:  variable not used' warning is not
  45. //    generated during a compile.  This macro should not cause any code to be generated.
  46. #ifndef __UNUSED__
  47. #define unused(x) ((void) &x)
  48. #define __UNUSED__
  49. #endif
  50.  
  51.  
  52. #define majorDebug 0
  53. #define debugCallback 0
  54.  
  55.  
  56. #pragma segment TADASTupleDatabase
  57.  
  58. Boolean SetupAttributeTypeFromKey (AttributeType* attrType, void* key, long keySize) {
  59.     attrType->charSet = smRoman;
  60.     attrType->dataLength = shortmin((short) keySize, kAttributeTypeMaxBytes);
  61.     BlockMove((Ptr) key, (Ptr) &(attrType->body), attrType->dataLength);
  62.  
  63.     return true;
  64. };
  65.  
  66. Boolean SetupAttributeValueFromData(AttributeValue& attrValue, void* data, long dataSize) {
  67.     attrValue.tag = typeBinary;
  68.     attrValue.dataLength = shortmin((short) dataSize, 32767);
  69.     attrValue.bytes = (Ptr) data;
  70.  
  71.     return true;
  72. };
  73.  
  74. RStringPtr NewCopyRStringPtr (RStringPtr r) {
  75.     RStringPtr result = nil;
  76.     if (r) {
  77.         result = (RStringPtr) FAILNewPtr( r->dataLength + 4);
  78.         result->dataLength = r->dataLength;
  79.         result->charSet = r->charSet;
  80.         BlockMove ((Ptr) r->body, (Ptr) result->body, r->dataLength);
  81.     };
  82.     return result;
  83. };
  84.  
  85.  
  86. TADASTupleDatabase::TADASTupleDatabase()
  87. {
  88.     fAuthIdentity = 0;
  89.     fRecordIDPtr = nil;
  90.     fDirRefNum = 0;
  91. };
  92.  
  93. TADASTupleDatabase::~TADASTupleDatabase () {
  94.     if (fRecordIDPtr) {
  95.         DeallocatePtr((Ptr) fRecordIDPtr->rli);
  96.         DeallocatePtr((Ptr) fRecordIDPtr);
  97.     };
  98. };
  99.  
  100. typedef struct InfoPassedToCallbackRec {
  101.     short            currentAttrIndex;        // the index of the current attribute, from 1 .. N
  102.     short            attrIndexDesired;
  103.  
  104.     short            currentAttrValueIndex;    // the index of the current attribute value, from 1..M
  105.     short            attrValueIndexDesired;
  106.  
  107.     AttributeTag    tag;
  108.     CreationID        cid;
  109.     void*            data;
  110.     long            dataSize;
  111. };
  112.  
  113. pascal Boolean OurForEachLocalRecordID(long clientData, const RecordID* recordID) {
  114.     unused(recordID);
  115.     InfoPassedToCallbackRec*    infoPassedToCallback = (InfoPassedToCallbackRec*) clientData;
  116.  
  117. #if debugCallback
  118.     if (keithFlag.Flag(9)) {
  119.         keith << "OurForEachRecordID: "; keith.write((char*) recordID->name->body, recordID->name->dataLength); keith << endl << flush;
  120.     };
  121. #endif
  122.  
  123.     infoPassedToCallback->currentAttrIndex = 0;
  124.     infoPassedToCallback->currentAttrValueIndex = 0;
  125.  
  126.     return false;
  127. };
  128.  
  129.  
  130. pascal Boolean OurForEachAttrType(long clientData, const AttributeType* attrType, AccessMask attrAccessMask) {
  131.     unused(attrType); unused(attrAccessMask);
  132.     InfoPassedToCallbackRec*    infoPassedToCallback = (InfoPassedToCallbackRec*) clientData;
  133.  
  134. #if debugCallback
  135.     if (keithFlag.Flag(9)) {
  136.         keith << "OurForEachAttrType: attrType="; keith.write((char*) attrType->body, attrType->dataLength); keith << endl << flush;
  137.     };
  138. #endif
  139.  
  140.     infoPassedToCallback->currentAttrIndex += 1;
  141.     infoPassedToCallback->currentAttrValueIndex = 0;
  142.  
  143.     return false;
  144. };
  145.  
  146. pascal Boolean OurForEachAttrValue(long clientData, const Attribute* attr) {
  147.     InfoPassedToCallbackRec*    infoPassedToCallback = (InfoPassedToCallbackRec*) clientData;
  148.  
  149.     if (attr) {
  150.         ++infoPassedToCallback->currentAttrValueIndex;
  151.  
  152. #if debugCallback
  153.         if (keithFlag.Flag(9)) {
  154.             keith << "OurForEachAttrValue: attrTag=" << attr->value.tag << " size=" << attr->value.u.binary.dataLength <<
  155.                 " index=" << infoPassedToCallback->currentAttrValueIndex <<
  156.                 " desired=" << infoPassedToCallback->attrValueIndexDesired <<
  157.                 " (" << infoPassedToCallback->currentAttrIndex << "," << infoPassedToCallback->attrIndexDesired << ")" << endl << flush;
  158.         };
  159. #endif
  160.  
  161.         if ((infoPassedToCallback->currentAttrIndex == infoPassedToCallback->attrIndexDesired) &&
  162.             (infoPassedToCallback->currentAttrValueIndex == infoPassedToCallback->attrValueIndexDesired)) {
  163.  
  164. #if debug
  165.             if (keithFlag.Flag(9))
  166.                 keith << "OurForEachAttrValue: Matched!, attrType=" << * (RStringPtr) &attr->attributeType << " dataSize=" << attr->value.dataLength << endl;
  167. #endif
  168.  
  169.             infoPassedToCallback->tag = attr->value.tag;
  170.             infoPassedToCallback->cid = attr->cid;
  171.             if (attr->value.tag == typeBinary) {
  172.                 if (infoPassedToCallback->data) {
  173.                     infoPassedToCallback->dataSize = shortmin((short) infoPassedToCallback->dataSize, (short) attr->value.dataLength);
  174.                     BlockMove ((Ptr) attr->value.bytes, (Ptr) infoPassedToCallback->data, infoPassedToCallback->dataSize);
  175.                 } else {
  176.                     infoPassedToCallback->dataSize = attr->value.dataLength;
  177.                 };
  178.             };
  179.             return true;
  180.         };
  181.     };
  182.  
  183.     return false;
  184. };
  185.  
  186.  
  187.  
  188. //    This function will get the index-th attribute of the given type from our record.  We return the cid, tag, and dataSize bytes of the attribute data.
  189. Boolean TADASTupleDatabase::GetAttributeFromADASAttributeTypeAndIndex(AttributeType& attrType, long index, CreationID& cid, AttributeTag& tag, void* data, long& dataSize) {
  190.  
  191.     DirLookupGetPB lookupPB;
  192.  
  193.     RecordIDPtr recordArray[1];
  194.     recordArray[0] = fRecordIDPtr;
  195.  
  196.     AttributeTypePtr attributeArray[1];
  197.     attributeArray[0] = &attrType;
  198.  
  199.     Ptr buffer = nil;
  200.  
  201.     if ((data) && (dataSize > 0)) {
  202.         buffer = FAILNewPtrClear(dataSize + 512);
  203.     } else {
  204.         buffer = FAILNewPtrClear(128);
  205.     };
  206.  
  207.     if (buffer == nil)
  208.         return false;
  209.  
  210.     memset(&lookupPB, 0, sizeof(lookupPB));
  211.     lookupPB.ioCompletion = nil;
  212.     lookupPB.serverHint = fServerHint;
  213.     lookupPB.dsRefNum = fDirRefNum;
  214.     lookupPB.identity = fAuthIdentity;
  215.     lookupPB.clientData = nil;
  216.     lookupPB.aRecordList = recordArray;
  217.     lookupPB.recordIDCount = 1;
  218.     lookupPB.attrTypeCount = 1;
  219.     lookupPB.attrTypeList = attributeArray;
  220.     lookupPB.getBuffer = buffer;
  221.     lookupPB.getBufferSize = GetPtrSize(buffer);
  222.     lookupPB.startingRecordIndex = 1;
  223.     lookupPB.startingAttrTypeIndex = 1;
  224.  
  225.     lookupPB.startingAttribute.attributeType = attrType;
  226.     OCESetCreationIDtoNull(&lookupPB.startingAttribute.cid);
  227.  
  228.     InfoPassedToCallbackRec callbackInfo;
  229.     memset(&callbackInfo, 0, sizeof(callbackInfo));
  230.     callbackInfo.data = data;
  231.     callbackInfo.dataSize = dataSize;
  232.     callbackInfo.attrIndexDesired = 1;
  233.     callbackInfo.attrValueIndexDesired = (short) index;
  234.  
  235.     OSErr err = noErr;
  236.  
  237.     do {
  238.         err = DirLookupGetSleep((DirParamBlockPtr) &lookupPB);
  239.  
  240. #if debug
  241.         if ((err) && (err != kOCEMoreData)) {
  242.             keith << "GetAttributeFrom…/DSLookupGet: err#=" << err << endl << flush;
  243.         };
  244. #endif
  245.  
  246.         if ((err == noErr) || (err == kOCEMoreData) || (err == kOCEMoreAttrValue)) {
  247.             DirLookupParsePB    parsePB;
  248.  
  249.             parsePB.aRecordList = lookupPB.aRecordList;
  250.             parsePB.attrTypeList = lookupPB.attrTypeList;
  251.             parsePB.recordIDCount = lookupPB.recordIDCount;
  252.             parsePB.attrTypeCount = lookupPB.attrTypeCount;
  253.             parsePB.getBuffer = lookupPB.getBuffer;
  254.             parsePB.getBufferSize = lookupPB.getBufferSize;
  255.  
  256.             parsePB.eachRecordID = OurForEachLocalRecordID;
  257.             parsePB.eachAttrType = OurForEachAttrType;
  258.             parsePB.eachAttrValue = OurForEachAttrValue;
  259.             parsePB.clientData = (long) &callbackInfo;
  260.  
  261.             err = DirLookupParseSleep((DirParamBlockPtr) &parsePB);
  262.  
  263. #if debug
  264.             if (err)
  265.                 keith << "GetAttributeFrom…/DirLookupParse: err#=" << err << endl << flush;
  266. #endif
  267.  
  268.             if ((err == noErr) && (callbackInfo.currentAttrValueIndex == index)) {
  269.                 dataSize = callbackInfo.dataSize;
  270.                 OCECopyCreationID(&callbackInfo.cid, &cid);
  271.                 tag = callbackInfo.tag;
  272.                 DeallocatePtr(buffer);
  273.  
  274. #if debug
  275.                 if (keithFlag.Flag(9))
  276.                     keith << " Matched!  dataSize=" << dataSize << " cid=" << cid.source << "," << cid.seq << " tag=" << tag << endl << flush;
  277. #endif
  278.  
  279.                 return true;
  280.             } else {
  281.                 if (err == kOCEMoreAttrValue) {
  282.                     dataSize = parsePB.attrSize;
  283.                     return false;
  284.                 };
  285.             };
  286.         };
  287.     } while ((err == kOCEMoreData) || (err == kOCEMoreAttrValue));
  288.  
  289.     DeallocatePtr(buffer);
  290.     return false;
  291. };
  292.  
  293. Boolean TADASTupleDatabase::GetTupleSize(void* key, long keySize, long &dataSize) {
  294.     AttributeType attrType;
  295.     CreationID attrCID;
  296.     AttributeTag attrTag;
  297.  
  298.     SetupAttributeTypeFromKey(&attrType, key, keySize);
  299.     dataSize = 0;
  300.     if (GetAttributeFromADASAttributeTypeAndIndex(attrType, 1, attrCID, attrTag, nil, dataSize)) {
  301. #if debug
  302.         if (keithFlag.Flag(9)) {
  303.             keith << "TADAS…:GetTupleSize('"; keith.write((char*) key, (int) keySize); keith << "') returning TRUE, size = " << dataSize << endl << flush;
  304.         };
  305. #endif
  306.         return true;
  307.     }
  308.  
  309. #if debug
  310.     if (keithFlag.Flag(9)) {
  311.         keith << "TADAS…:GetTupleSize('"; keith.write((char*) key, (int) keySize); keith << "') returning FALSE." << endl << flush;
  312.     };
  313. #endif
  314.     dataSize = 0;
  315.     return false;
  316. };
  317.  
  318.  
  319. Boolean TADASTupleDatabase::GetTuple(void* key, long keySize) {
  320.     long    actualSize = 0, dataSize = 0;
  321.  
  322.     return GetTuple(key, keySize, actualSize, nil, dataSize);
  323. };
  324.  
  325. Boolean TADASTupleDatabase::GetTuple(void* key, long keySize, long& actualDataSize, void *data, long dataSize) {
  326.     AttributeType attrType;
  327.     CreationID attrCID;
  328.     AttributeTag attrTag;
  329.  
  330.     SetupAttributeTypeFromKey(&attrType, key, keySize);
  331.     if (GetAttributeFromADASAttributeTypeAndIndex(attrType, 1, attrCID, attrTag, data, dataSize)) {
  332. #if debug
  333.         if (keithFlag.Flag(9)) {
  334.             keith << "TADAS…:GetTuple('"; keith.write((char*) key, (int) keySize); keith << " TRUE, data (" << dataSize << ") '";
  335.             keith.write((char*) data, (int) shortmin(1024, dataSize)); keith << "'" << endl << flush;
  336.         };
  337. #endif
  338.         actualDataSize = dataSize;
  339.         return true;
  340.     };
  341.  
  342. #if debug
  343.     if (keithFlag.Flag(9)) {
  344.         keith << "TADAS…:GetTuple('"; keith.write((char*) key, (int) keySize); keith << " FALSE." << endl << flush;
  345.     };
  346. #endif
  347.     actualDataSize = 0;
  348.     return false;
  349. };
  350.  
  351. Boolean TADASTupleDatabase::SetTuple(void *key, long keySize, void *data, long dataSize) {
  352.     Attribute attr;
  353.     AttributeTag attrTag;
  354.     OSErr err = noErr;
  355.  
  356.     SetupAttributeTypeFromKey(&attr.attributeType, key, keySize);
  357.     SetupAttributeValueFromData (attr.value, data, dataSize);
  358.     
  359.     long temp = 0; // this is ahack to fix a  non-const ref to 0 bug-pfl
  360.  
  361.     if (GetAttributeFromADASAttributeTypeAndIndex( attr.attributeType, 1, attr.cid, attrTag, nil, temp)) {
  362.         DirDeleteAttributeValuePB        changeAttrPB;
  363.  
  364. #if debug
  365.         if (keithFlag.Flag(9)) {
  366.             keith << "TADAS…:SetTuple('"; keith.write((char*) key, (int) keySize); keith << " <R> data (" << dataSize << ") '";
  367.             keith.write((char*) data, (int) shortmin(1024, dataSize)); keith << "'" << endl << flush;
  368.         };
  369. #endif
  370.  
  371.         attr.value.tag = typeBinary;
  372.         attr.value.dataLength = shortmin((short) dataSize, 32767);
  373.         attr.value.bytes = (char*) data;
  374.  
  375.         memset(&changeAttrPB, 0, sizeof(changeAttrPB));
  376.         changeAttrPB.serverHint = fServerHint;
  377.         changeAttrPB.dsRefNum = fDirRefNum;
  378.         changeAttrPB.identity = fAuthIdentity;
  379.         changeAttrPB.clientData = nil;
  380.         changeAttrPB.aRecord = fRecordIDPtr;
  381.         changeAttrPB.attr = &attr;
  382.  
  383.         err = DirChangeAttributeValueSleep((DirParamBlockPtr) &changeAttrPB);
  384.  
  385. #if debug
  386.         if (err) keith << "SetTuple/DirChangeAttribute: err#=" << err << endl << flush;
  387. #endif
  388.  
  389.         return (err == noErr);
  390.     } else {
  391.         DirAddAttributeValuePB        addAttrPB;
  392.  
  393. #if debug
  394.         if (keithFlag.Flag(9)) {
  395.             keith << "TADAS…:SetTuple('"; keith.write((char*) key, (int) keySize); keith << " <A> data (" << dataSize << ") '";
  396.             keith.write((char*) data, (int) shortmin(1024, dataSize)); keith << "'" << endl << flush;
  397.         };
  398. #endif
  399.  
  400.         OCESetCreationIDtoNull(&attr.cid);
  401.  
  402.         memset(&addAttrPB, 0, sizeof(addAttrPB));
  403.         addAttrPB.ioCompletion = nil;
  404.         addAttrPB.serverHint = fServerHint;
  405.         addAttrPB.dsRefNum = fDirRefNum;
  406.         addAttrPB.identity = fAuthIdentity;
  407.         addAttrPB.clientData = nil;
  408.         addAttrPB.aRecord = fRecordIDPtr;
  409.         addAttrPB.attr = &attr;
  410.  
  411.         err = DirAddAttributeValueSleep((DirParamBlockPtr) &addAttrPB);
  412.  
  413. #if debug
  414.         if (err) keith << "SetTuple/DirAddAttribute: err#=" << err << endl << flush;
  415. #endif
  416.     };
  417.  
  418.     return (err == noErr);
  419. };
  420.  
  421.  
  422. Boolean TADASTupleDatabase::DeleteTuple(void *key, long keySize) {
  423.     DirDeleteAttributeTypePB deleteAttrPB;
  424.     AttributeType attrType;
  425.  
  426. #if debug
  427.     if (keithFlag.Flag(9)) {
  428.         keith << "TADAS…:DeleteTuple('"; keith.write((char*) key, (int) keySize); keith << endl << flush;
  429.     };
  430. #endif
  431.  
  432.     SetupAttributeTypeFromKey(&attrType, key, keySize);
  433.  
  434.     memset(&deleteAttrPB, 0, sizeof(deleteAttrPB));
  435.     deleteAttrPB.ioCompletion = nil;
  436.     deleteAttrPB.serverHint = fServerHint;
  437.     deleteAttrPB.dsRefNum = fDirRefNum;
  438.     deleteAttrPB.identity = fAuthIdentity;
  439.     deleteAttrPB.clientData = nil;
  440.     deleteAttrPB.aRecord = fRecordIDPtr;
  441.     deleteAttrPB.attrType = &attrType;
  442.  
  443.     OSErr err = DirDeleteAttributeTypeSleep((DirParamBlockPtr) &deleteAttrPB);
  444.     if (err) keith << "DeleteTuple/DirDeleteAttributeValue, err#=" << err << endl << flush;
  445.  
  446.     return (err == noErr);
  447. };
  448.  
  449. pascal Boolean CountTuplesForEachAttrType (long clientData, const AttributeType* attrType) {
  450.     long*    count = (long*) clientData;
  451.  
  452.     if (attrType) {
  453.         (*count)++;
  454. #if debugCallback
  455.         if (keithFlag.Flag(9)) {
  456.             keith << "CountTuplesForEachAttrType, type=" << (RStringPtr) attrType << endl << flush;
  457.         };
  458. #endif
  459.     };
  460.     return false;
  461. };
  462.  
  463. long TADASTupleDatabase::CountTuples() {
  464.     long    result = 0;
  465.  
  466.     DirEnumerateAttributeTypesGetPB enumeratePB;
  467.  
  468.     //    We do a count of the number of tuples available by counting the number of attributes.
  469.     memset(&enumeratePB, 0, sizeof(enumeratePB));
  470.     enumeratePB.ioCompletion = nil;
  471.     enumeratePB.serverHint = fServerHint;
  472.     enumeratePB.dsRefNum = fDirRefNum;
  473.     enumeratePB.identity = fAuthIdentity;
  474.     enumeratePB.clientData = (long) &result;
  475.     enumeratePB.aRecord = fRecordIDPtr;
  476.     enumeratePB.getBuffer = FAILNewPtrClear(8192); // this is big for now, because there's no way to
  477.                                                                             // continue an enumerateAttributeTypes.  When there
  478.                                                                             // is, this should allocate a small buffer & loop
  479.     enumeratePB.getBufferSize = GetPtrSize((Ptr) enumeratePB.getBuffer);
  480.  
  481.     OSErr err = noErr;
  482.     do {
  483.         err = DirEnumerateAttributeTypesGetSleep((DirParamBlockPtr) &enumeratePB);
  484.  
  485. #if debug
  486.         if (err) keith << "CountTuples/DirLookupGet: err#=" << err << endl << flush;
  487. #endif
  488.  
  489.         if ((err == noErr) || (err == kOCEMoreData) || (err == kOCEMoreAttrValue)) {
  490.             DirEnumerateAttributeTypesParsePB parsePB;
  491.  
  492.             parsePB.aRecord = enumeratePB.aRecord;
  493.             parsePB.eachAttrType = CountTuplesForEachAttrType;
  494.             parsePB.getBuffer = enumeratePB.getBuffer;
  495.             parsePB.getBufferSize = enumeratePB.getBufferSize;
  496.  
  497.             err = DirEnumerateAttributeTypesParseSleep((DirParamBlockPtr) &parsePB);
  498.  
  499. #if debug
  500.             if (err) keith << "CountTuples/DirEnumerateAttributeTypesParse, err#=" << err << endl << flush;
  501. #endif
  502.         };
  503.     } while ((err == kOCEMoreData) || (err == kOCEMoreAttrValue));
  504.  
  505.     DeallocatePtr((Ptr) enumeratePB.getBuffer);
  506.  
  507.     return result;
  508. };
  509.  
  510. typedef struct GetIndexAttributeCallbackInfoRec {
  511.     long                remainingCount;
  512.     Boolean                found;
  513.     AttributeTypePtr     attrType;
  514. };
  515.  
  516. pascal Boolean GetIndexAttributeForEachAttrType (long clientData, const AttributeType* attrType) {
  517.     GetIndexAttributeCallbackInfoRec* info = (GetIndexAttributeCallbackInfoRec*) clientData;
  518.  
  519.     if (attrType) {
  520. #if debugCallback
  521.         if (keithFlag.Flag(9)) {
  522.             keith << "GetIndexAttributeForEachAttrType, count=" << info->remainingCount << " " << (RStringPtr) attrType << endl << flush;
  523.         };
  524. #endif
  525.  
  526.         info->remainingCount -= 1;
  527.  
  528.         if (info->remainingCount == 0) {
  529.             info->found = true;
  530.             OCECopyRString ((RStringPtr) attrType, (RStringPtr) info->attrType, kAttributeTypeMaxBytes);
  531.             return true;
  532.         };
  533.     };
  534.     return false;
  535. };
  536.  
  537. Boolean TADASTupleDatabase::GetIndexAttribute (long i, AttributeType& attrType) {
  538.     GetIndexAttributeCallbackInfoRec callbackInfo;
  539.  
  540.     //    Indexes start with 1
  541.     if (i < 1)
  542.         return false;
  543.  
  544.     callbackInfo.remainingCount = i;
  545.     callbackInfo.found = false;
  546.     callbackInfo.attrType = &attrType;
  547.  
  548. #if debug
  549.     if (keithFlag.Flag(9)) {
  550.         keith << "GetIndexAttribute: entering, index=" << i << endl << flush;
  551.     };
  552. #endif
  553.  
  554.     //    We do a count of the number of tuples available by counting the number of attributes.
  555.     DirEnumerateAttributeTypesGetPB enumeratePB;
  556.     memset(&enumeratePB, 0, sizeof(enumeratePB));
  557.     enumeratePB.ioCompletion = nil;
  558.     enumeratePB.serverHint = fServerHint;
  559.     enumeratePB.dsRefNum = fDirRefNum;
  560.     enumeratePB.identity = fAuthIdentity;
  561.     enumeratePB.clientData = (long) &callbackInfo;
  562.     enumeratePB.aRecord = fRecordIDPtr;
  563.     enumeratePB.getBuffer = FAILNewPtrClear(8192);     // this is big for now, because there's no way to
  564.                                                         // continue an enumerateAttributeTypes.  When there
  565.                                                         // is, this should allocate a small buffer & loop
  566.     enumeratePB.getBufferSize = GetPtrSize((Ptr) enumeratePB.getBuffer);
  567.  
  568.     OSErr err = noErr;
  569.     do {
  570.         err = DirEnumerateAttributeTypesGetSleep((DirParamBlockPtr) &enumeratePB);
  571.  
  572. #if debug
  573.         if (err) keith << "GetIndexAttribute/DirEnumerateAttributeTypesGet: err#=" << err << endl << flush;
  574. #endif
  575.  
  576.         if ((err == noErr) || (err == kOCEMoreData) || (err == kOCEMoreAttrValue)) {
  577.             DirEnumerateAttributeTypesParsePB parsePB;
  578.  
  579.             parsePB.aRecord = enumeratePB.aRecord;
  580.             parsePB.eachAttrType = GetIndexAttributeForEachAttrType;
  581.             parsePB.getBuffer = enumeratePB.getBuffer;
  582.             parsePB.getBufferSize = enumeratePB.getBufferSize;
  583.  
  584.             err = DirEnumerateAttributeTypesParseSleep((DirParamBlockPtr) &parsePB);
  585.  
  586. #if debug
  587.             if (err) keith << "GetIndexAttribute/DirEnumerateAttributeTypesParse, err#=" << err << endl << flush;
  588. #endif
  589.         };
  590.     } while ((err == kOCEMoreData) || (err == kOCEMoreAttrValue));
  591.  
  592.     DeallocatePtr((Ptr) enumeratePB.getBuffer);
  593.  
  594.     return callbackInfo.found;
  595. };
  596.  
  597.  
  598. Boolean TADASTupleDatabase::GetIndexTuple(long i, void *key, long &keySize) {
  599.     long    dataSize = 0;
  600.  
  601.     return GetIndexTuple(i, key, keySize, nil, dataSize);
  602. };
  603.  
  604. Boolean TADASTupleDatabase::GetIndexTuple(long i, void *key, long& keySize, void *data, long &dataSize) {
  605.     AttributeType            attrType;
  606.  
  607.     if (GetIndexAttribute (i, attrType)) {
  608.         //    Copy the attribute back to the user supplied key
  609.         if ((key) && (keySize > 0)) {
  610.             keySize = longmin(keySize, attrType.dataLength);
  611.             BlockMove((Ptr) attrType.body, (Ptr) key, keySize);
  612.         };
  613.  
  614.         if ((data) && (dataSize > 0)) {
  615.             CreationID attrCID;
  616.             AttributeTag attrTag;
  617.             if (GetAttributeFromADASAttributeTypeAndIndex(attrType, 1, attrCID, attrTag, data, dataSize))
  618.                 return true;
  619.             dataSize = 0;
  620.             return false;
  621.         } else {
  622.             //    Don't return any data, but do return the correct dataSize.
  623.             CreationID attrCID;
  624.             AttributeTag attrTag;
  625.             dataSize = 0;
  626.             if (GetAttributeFromADASAttributeTypeAndIndex(attrType, 1, attrCID, attrTag, nil, dataSize))
  627.                 return true;
  628.             dataSize = 0;
  629.             return false;
  630.         };
  631.         return true;
  632.     };
  633.  
  634.     dataSize = 0;
  635.     return false;
  636. };
  637.  
  638. Boolean TADASTupleDatabase::FindIndexOfTuple(void *key, long keySize, long &i) {
  639.     unused(key); unused(keySize); unused(i);
  640.  
  641.  
  642.     return false;
  643. };
  644.  
  645. Boolean TADASTupleDatabase::SetIndexTuple(long i, void *data, long dataSize) {
  646.     Attribute attr;
  647.  
  648.     if (GetIndexAttribute (i, attr.attributeType)) {
  649.         AttributeTag attrTag;
  650.  
  651. #if debug
  652.         if (keithFlag.Flag(9)) {
  653.             keith << "SetIndexTuple: index=" << i << " key="; keith.write((char*)attr.attributeType.body, (int) attr.attributeType.dataLength); keith << " length=" << attr.attributeType.dataLength << endl << flush;
  654.         };
  655. #endif
  656.  
  657.         SetupAttributeValueFromData (attr.value, data, dataSize);
  658.         
  659.         long temp = 0;
  660.  
  661.         if (GetAttributeFromADASAttributeTypeAndIndex(attr.attributeType, 1, attr.cid, attrTag, nil, temp)) {
  662.             Attribute    newAttr;
  663.  
  664.             newAttr.value.tag = typeBinary;
  665.             newAttr.value.dataLength = shortmin((short) dataSize, 32767);
  666.             newAttr.value.bytes = (char*) data;
  667.  
  668.             DirChangeAttributeValuePB pb;
  669.             memset(&pb, 0, sizeof(pb));
  670.             pb.ioCompletion = nil;
  671.             pb.serverHint = fServerHint;
  672.             pb.dsRefNum = fDirRefNum;
  673.             pb.identity = fAuthIdentity;
  674.             pb.clientData = nil;
  675.             pb.aRecord = fRecordIDPtr;
  676.             pb.currentAttr = &attr;
  677.             pb.newAttr = &newAttr;
  678.  
  679.             OSErr err = DirChangeAttributeValueSleep ((DirParamBlockPtr) &pb);
  680.  
  681. #if debug
  682.             if (err) keith << "SetIndexTuple/DirChangeAttribute: err#=" << err << endl << flush;
  683. #endif
  684.  
  685.             return (err == noErr);
  686.         };
  687.     };
  688.  
  689.     return false;
  690. };
  691.  
  692. pascal Boolean IADASTupleDatabaseForEachLocalRecordID (long clientData, const DirEnumSpec *enumSpecPtr) {
  693.     RecordIDPtr        recordIDPtr = (RecordIDPtr) clientData;
  694.  
  695.     if ((recordIDPtr) && (enumSpecPtr) && (enumSpecPtr->enumFlag & kEnumDistinguishedNameMask)) {
  696.         recordIDPtr->local.cid = enumSpecPtr->u.recordIdentifier.cid;
  697.         return true;
  698.     };
  699.  
  700.     return false;
  701. };
  702.  
  703. Boolean TADASTupleDatabase::IADASTupleDatabase (AuthIdentity identityToUse, short dsRefNum, RecordIDPtr ourRecord, AddrBlock* serverHint) {
  704.  
  705.     fAuthIdentity = identityToUse;
  706.     fDirRefNum = dsRefNum;
  707.  
  708.     if (ourRecord == nil)
  709.         return false;
  710.  
  711.     fRecordIDPtr = (RecordIDPtr) FAILNewPtrClear(sizeof(*fRecordIDPtr));
  712.     if (fRecordIDPtr == nil)
  713.         return false;
  714.  
  715.     fRecordIDPtr->local.recordName = NewCopyRStringPtr(ourRecord->local.recordName);
  716.     fRecordIDPtr->local.recordType = NewCopyRStringPtr(ourRecord->local.recordType);
  717.  
  718.     OCECopyLocalRecordID(&ourRecord->local, &fRecordIDPtr->local);
  719.  
  720.     fRecordIDPtr->rli = (PackedRLIPtr) FAILNewPtr(ourRecord->rli->dataLength + sizeof(ProtoPackedRLI));
  721.     if (fRecordIDPtr->rli == nil) {
  722.         return false;
  723.     };
  724.     OCECopyPackedRLI (ourRecord->rli, fRecordIDPtr->rli, (unsigned short) GetPtrSize((Ptr) fRecordIDPtr->rli));
  725.  
  726.     if (serverHint) {
  727.         fServerHint = *serverHint;
  728.     } else {
  729.         fServerHint.aNet = 0;
  730.         fServerHint.aNode = fServerHint.aSocket = 0;
  731.     };
  732.  
  733.     //    Now, we need to enumerate the ADAS directory in order to get the #)*(#$ CID for the record
  734.     //    we use.  Why there isn't a single call to do this, I don't know.
  735.  
  736.     Boolean result = false;
  737.     {    DirEnumerateGetPB enumeratePB;
  738.  
  739.         memset(&enumeratePB, 0, sizeof(enumeratePB));
  740.         enumeratePB.serverHint = fServerHint;
  741.         enumeratePB.dsRefNum = fDirRefNum;
  742.         enumeratePB.identity = fAuthIdentity;
  743.         enumeratePB.clientData = (long) fRecordIDPtr;
  744.         enumeratePB.aRLI = fRecordIDPtr->rli;
  745.         enumeratePB.startingPoint = nil;
  746.         enumeratePB.sortBy = kSortByName;
  747.         enumeratePB.sortDirection = kSortForwards;
  748.         enumeratePB.nameMatchString = fRecordIDPtr->local.recordName;
  749.         enumeratePB.typesList = & (fRecordIDPtr->local.recordType);
  750.         enumeratePB.typeCount = 1;
  751.         enumeratePB.enumFlags = kEnumDistinguishedNameMask;
  752.         enumeratePB.includeStartingPoint = false;
  753.         enumeratePB.getBuffer = FAILNewPtrClear(128);
  754.         enumeratePB.getBufferSize = GetPtrSize((Ptr) enumeratePB.getBuffer);
  755.         // enumeratePB.requestScriptCode = smRoman;
  756.  
  757.         OSErr err = DirEnumerateGetSleep((DirParamBlockPtr) &enumeratePB);
  758.  
  759.         if (err == noErr) {
  760.             DirEnumerateParsePB parsePB;
  761.  
  762.             parsePB.aRLI = enumeratePB.aRLI;
  763.             parsePB.eachEnumSpec = IADASTupleDatabaseForEachLocalRecordID;
  764.             parsePB.getBuffer = enumeratePB.getBuffer;
  765.             parsePB.getBufferSize = enumeratePB.getBufferSize;
  766.  
  767.             err = DirEnumerateParseSleep((DirParamBlockPtr) &parsePB);
  768.  
  769.             if ((fRecordIDPtr->local.cid.source != 0) || (fRecordIDPtr->local.cid.seq != 0))
  770.                 result = true;
  771.         };
  772.  
  773.         DeallocatePtr((Ptr) enumeratePB.getBuffer);
  774.     };
  775.  
  776.     return result;
  777. };
  778.  
  779. Boolean TADASTupleDatabase::CreateDatabase() {
  780.  
  781.     if (fRecordIDPtr == nil)
  782.         return false;
  783.  
  784.     DirAddRecordPB addRecordPB;
  785.  
  786.     memset(&addRecordPB, 0, sizeof(addRecordPB));
  787.     addRecordPB.ioCompletion = nil;
  788.     addRecordPB.serverHint = fServerHint;
  789.     addRecordPB.dsRefNum = fDirRefNum;
  790.     addRecordPB.identity = fAuthIdentity;
  791.     addRecordPB.clientData = 0;
  792.     addRecordPB.aRecord = fRecordIDPtr;
  793.     addRecordPB.allowDuplicate = false;
  794.  
  795.     OSErr err = DirAddRecordSleep((DirParamBlockPtr) &addRecordPB);
  796.  
  797. #if debug
  798.     if (err) keith << "CreateDatabase/DirAddRecord err#=" << err << endl << flush;
  799. #endif
  800.  
  801.     return (err == noErr);
  802. };
  803.  
  804. Boolean TADASTupleDatabase::DeleteDatabase () {
  805.     if (fRecordIDPtr == nil)
  806.         return false;
  807.  
  808.     DirDeleteRecordPB deleteRecordPB;
  809.  
  810.     memset(&deleteRecordPB, 0, sizeof(deleteRecordPB));
  811.     deleteRecordPB.ioCompletion = nil;
  812.     deleteRecordPB.serverHint = fServerHint;
  813.     deleteRecordPB.dsRefNum = fDirRefNum;
  814.     deleteRecordPB.identity = fAuthIdentity;
  815.     deleteRecordPB.clientData = 0;
  816.     deleteRecordPB.aRecord = fRecordIDPtr;
  817.  
  818.     OSErr err = DirDeleteRecordSleep((DirParamBlockPtr) &deleteRecordPB);
  819.  
  820. #if debug
  821.     if (err) keith << "DeleteDatabase/DirDeleteRecord err#=" << err << endl << flush;
  822. #endif
  823.  
  824.     return (err == noErr);
  825. };
  826.  
  827.  
  828. void TADASTupleDatabase::Flush(void) {
  829.     //    Right now, don't do anything.  Maybe we never will have to do anything.
  830.  
  831. };
  832. #endif